local BuffManager = class("BuffManager")
local Vector3 = require("utils.Vector3")
local GameUtils = require("utils.GameUtils")

function BuffManager:ctor()
    self._buffList = {}
    self._removeList = {}
    self:initListener()
end

function BuffManager:initListener()
    self._signalRoundBegin =
        G_SignalManager:add(SignalConst.EVENT_ROUND_BEGIN_BUFF, handler(self, self._onEventRoundBegin))
    self._signalRoundEnd = G_SignalManager:add(SignalConst.EVENT_ROUND_END_BUFF, handler(self, self._onEventRoundEnd))
    self._signalActionBegin =
        G_SignalManager:add(SignalConst.EVENT_ACTION_BEGIN_BUFF, handler(self, self._onEventActionBegin))
    self._signalActionEnd =
        G_SignalManager:add(SignalConst.EVENT_ACTION_END_BUFF, handler(self, self._onEventActionEnd))
end

function BuffManager:_addBuff(buff)
    local entity = buff:getEntity()
    if entity then
        local buffs = self._buffList[entity] or {}
        if not buffs[buff:getId()] then
            buffs[buff:getId()] = self:_createBuffDisplayComponent(buff)
        end
        buffs[buff:getId()]:addChild(buff)
        self._buffList[entity] = buffs
        self:_layoutBuffs(buffs)
    end
end

function BuffManager:_createBuffDisplayComponent(buff)
    local entity = buff:getEntity()
    local whoEntity = buff:getWhoEntity()
    local component = require("gameLogic.buff.BuffDisplayComponent").new(self, entity, whoEntity, buff:getConfig())
    local GameUtils = require("utils.GameUtils")
    local BuffRes = "Buff"
    local bloodUI = entity:getBloodUI()
    local buffGameObject = GameUtils.instantiateTo(bloodUI.transform, G_ResourceManager:loadUI(BuffRes))
    local luaBehvoiur = buffGameObject:AddComponent(typeof(CS.LuaBehaviour))
    luaBehvoiur:SetScriptEnv(component)
    return component
end

function BuffManager:checkBuff(type, entity)
    if entity then
        self:_checkBuffList(self._buffList[entity], type)
    else
        for _, buffs in pairs(self._buffList) do
            self:_checkBuffList(buffs, type)
        end
    end
    self:_clearBuffList()
end

function BuffManager:_checkBuffList(buffs, type)
    if not buffs then
        return
    end
    for k, component in pairs(buffs) do
        if component:getType() == type then
            component:check()
        end
    end
end

function BuffManager:_clearBuffList()
    for i = 1, #self._removeList do
        self:_removeBuff(self._removeList[i])
    end
    self._removeList = {}
end

function BuffManager:destroy()
    self._signalActionBegin:remove()
    self._signalActionBegin = nil
    self._signalActionEnd:remove()
    self._signalActionEnd = nil
    self._signalRoundBegin:remove()
    self._signalRoundBegin = nil
    self._signalRoundEnd:remove()
    self._signalRoundEnd = nil
end

function BuffManager:_onEventRoundBegin(id, type)
    self:checkBuff(type)
end

function BuffManager:_onEventRoundEnd(id, type)
    self:checkBuff(type)
end

function BuffManager:_onEventActionBegin(id, type, entity)
    self:checkBuff(type, entity)
end

function BuffManager:_onEventActionEnd(id, type, entity)
    self:checkBuff(type, entity)
end

function BuffManager:addBuff(config, entity, whoEntity)
    local buff = require("gameLogic.buff.buffBase." .. config.class).new(entity, whoEntity, config)
    self:_addBuff(buff)
end

function BuffManager:_removeBuff(rmComponent)
    for _, buffs in pairs(self._buffList) do
        for k, component in pairs(buffs) do
            if component == rmComponent then
                GameUtils.destroy(component.gameObject)
                buffs[k] = nil
                self:_layoutBuffs(buffs)
                break
            end
        end
    end
end

function BuffManager:removeBuff(component)
    table.insert(self._removeList, component)
end

function BuffManager:_layoutBuffs(buffs)
    local i = 0
    for k, component in pairs(buffs) do
        component.transform.localPosition = Vector3.new(-53 + i * 26, -17, -0.5)
        i = i + 1
    end
end

return BuffManager
